package logica;
import java.util.Hashtable;
import java.util.ArrayList;
/**
**********************************************************************************************<br/>
*Crea un objeto del elemento mas importante de la aplicacion aqui:
* <ul>
* <li>Carga de archivo</li>
* <li>Comunicacion con la Interfaz grafica</li>
* <li>llamado a los algoritmos</li>
* </ul>
* @author Jefferson Amado Pe&ntilde;a Torres
**********************************************************************************************
* @see Vertice
* @see Asociacion
* @see Relacion
* @version 0.1
*/
public class Grafo{
	private	ArrayList <String>nombres; //nombre de todos los vertices
	private	ArrayList <Relacion>aristas;   //lista de aristas
	private	Hashtable <String,Vertice> nodos; //tabla hash (nombre,Vertice):
	private	ArrayList <String>nombreObjetivos; //nombre de todos los vertices objetivos
	//private int nVertices,nAristas,nObjetivos;
	/**
	*Contructor
	*/
	public Grafo(){
		nombres=new ArrayList<String>();
		nombreObjetivos=new ArrayList<String>();
		nodos=new Hashtable <String,Vertice>();
		aristas=new ArrayList <Relacion>();
		//System.out.println("<<< "+aristas);
	}
	/**
	*Agregar un vertice al grafo
	*@param nombre Nombre que se le asigna al nuevo vertice
	*/
	public void ingresarNodo(String nombre){
		nombres.add(nombre);
		nodos.put(nombre,new Vertice(nombre)); //nodo a la tabla hash
	}
	/**
	*establece un vertice objetivo al grafo
	*@param nombre Nombre que se le asigna al nuevo vertice
	*/
	public void ingresarVerticeObjetivo(String nombre){
		nombreObjetivos.add(nombre);
	}
	/**
	*Crea una relacion entre dos vertices del grafo desde sus nombres,organiza los enlaces segun su peso de manera ascendente
	*@param verticeA 
	*@param verticeB
	*@param costo valor de la relacion
	*/
	public void adicionarEnlace(String verticeA,String verticeB,double costo){
		//System.out.println("adicionarEnlace <:"+verticeA+" -> "+verticeB+" :> con costo:"+costo+" \n");
		Relacion nuevo=new Relacion(verticeA,verticeB,costo);
			int i=buscarPorSuPeso(nuevo.getCosto()); //trato de ubicarlas con un menor peso para ayudarle al algoritmo
			if(i==-1)aristas.add(nuevo);
			else aristas.add(i,nuevo);
			//aqui creo la comunicacion bidireccional entre los nodos
			nodos.get(verticeA).agregarEnlace(verticeB,costo);
			nodos.get(verticeB).agregarEnlace(verticeA,costo);
	}
	/**
	*Permite hallar una relacion entre dos vertices
	*@return <code>true<code> si existe la relacion<code>false<code> si no la encuentra
	*@param relacion elemento que une los dos vertices
	*/
	public boolean buscarArista(Relacion relacion){
		for(int i=0;i<aristas.size();i++){
				Relacion otro=aristas.get(i);
			if(relacion.getVerticePartida().equals(otro.getVerticePartida())&&relacion.getVerticeLlegada().equals(otro.getVerticeLlegada())&&relacion.getCosto()==otro.getCosto()){
					aristas.remove(otro);
				return true;
			}
		}
		return false;
	}
	/**
	*Permite hallar una relacion entre dos vertices
	*@return <code>true<code> si existe la relacion<code>false<code> si no la encuentra
	*@param relacion elemento que une los dos vertices
	*/
	public double buscarArista(String partida,String llegada){
		for(int i=0;i<aristas.size();i++){
				Relacion otro=aristas.get(i);
			if(partida.equals(otro.getVerticePartida())&&llegada.equals(otro.getVerticeLlegada()) || llegada.equals(otro.getVerticePartida())&&partida.equals(otro.getVerticeLlegada())){
					aristas.remove(otro);
				return otro.getCosto();
			}
		}
		return -1;
	}
	/**
	*Permite hallar las aristas segun su peso
	*@return <code>-1<code> si no hay una arista con mayor valor que el ingresado, de lo contrario retorna la posicion de la poscion
	*@param costo elemento que une los dos vertices
	*/
	public int buscarPorSuPeso(double costo){
		for(int i=0;i<aristas.size();i++){
			if(costo<aristas.get(i).getCosto())
				return i;
		}
		return -1;
	}
	/**
	*Retorna el numero de vertices en el grafo
	*@return numero de vertices
	*/
	public int getNVertices(){
		return nombres.size();
	}
	/**
	*Retorna el numero de relaciones en el grafo
	*@return relaciones en el grafo
	*/
	public int getNRelaciones(){
		return aristas.size();
	}
	/**
	*Retorna el numero de objetivos del grafo
	*@return numero de objetivos
	*/
	public int getNObjetivos(){
		return nombreObjetivos.size();
	}
	/**
	*Retorna un tabla hash con los nodos  ||nombre del vertice||vertice||
	*@return tabla hash con todo los nodos
	*/
	public Hashtable getNodos(){
		return nodos;
	}
	/**
	*Retorna la lista de todos los nombres que son objetivo de los vertices en el grafo
	*@return nombres de los nodos en el grafo
	*/
	public ArrayList<String> getNombresObjetivos(){
		return nombreObjetivos;
	}
	/**
	*Retorna la lista de todos los nombres de los vertices en el grafo
	*@return nombres de los nodos en el grafo
	*/
	public ArrayList<String> getNombres(){
		return nombres;
	}
	/**
	*Retorna un vertices en el grafo desde su nombre
	*@return Vertice desde su nombre
	*/
	public Vertice getVertice(String nombre){
		return (Vertice)nodos.get(nombre);
	}
	/**
	*Retorna todas las aristas que hay en el grafo
	*@return todas las aristas que posee el grafo
	*/
	public ArrayList<Relacion> getAristas() {
		//System.out.println("<<< "+aristas);
		return aristas;
	}
	/**
	*Establece todas las aristas que hay en el grafo
	*@param aristas todas las aristas que poseera el grafo
	*/
	public void setAristas(ArrayList<Relacion> aristas) {
		this.aristas = aristas;
	}
	/**
	*Establece la lista de nombre que recibiran los vertices
	*@param nombres todos los nombres de los vertices del grafo
	*/
	public void setNombres(ArrayList<String> nombres) {
		this.nombres = nombres;
	}
	/**
	*Establece un tabla hash con los nodos  ||nombre del vertice||vertice||
	*@param muchos tabla hash con todo los nodos para un grafo
	*/
	public void setVertices(Hashtable<String,Vertice > muchos){
		nodos=muchos;
	}
	
	/**
	*Establece la lista de todos los nombres que son objetivo de los vertices en el grafo
	*@param nombreObjetivos nombres de los vertices que seran objetivos
	*@deprecated no hace parte de la solucion para el proyecto
	*/
	@Deprecated
	public void setNombresObjetivos(ArrayList<String> nombreObjetivos){
		this.nombreObjetivos=nombreObjetivos;
	}
}
//Jefferson Amado Peña Torres
